package com.googlecode.horncomb.orm.id.generator;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.googlecode.horncomb.bean.id.generator.IdGenerator;

public class TableRecordIdGenerator extends JdbcDaoSupport implements
		IdGenerator<Long> {
	private String tableName = "SYS_IDGEN";
	private String keyColumn = "KEY_";
	private String key = "DEFAULT_ID";
	private String valueColumn = "CURR_VAL_";
	private int step = 1;

	private Long generateId() {

		Long currId = (Long) this.getJdbcTemplate().execute(
				this.getCurrentIdSql(), new PreparedStatementCallback<Long>() {
					public Long doInPreparedStatement(PreparedStatement stmt)
							throws SQLException, DataAccessException {
						ResultSet rs = stmt.executeQuery();
						rs.next();
						Long id = rs.getLong(keyColumn);
						return id;
					}
				});
		final long nextId = currId + step;
		this.getJdbcTemplate().execute(this.getUpdateNextIdSql(),
				new PreparedStatementCallback<Object>() {
					public Object doInPreparedStatement(PreparedStatement stmt)
							throws SQLException, DataAccessException {
						stmt.setLong(1, nextId);
						stmt.executeUpdate();
						return null;
					}
				});
		return nextId;
	}

	protected String getCurrentIdSql() {
		return new StringBuilder("SELECT ").append(valueColumn)
				.append(" FROM ").append(tableName).append(" WHERE ").append(
						keyColumn).append(" = '").append(key).append("'")
				.toString();
	}

	protected String getUpdateNextIdSql() {
		return new StringBuilder("UPDATE ").append(tableName).append(" SET ")
				.append(valueColumn).append("=? WHERE ").append(keyColumn)
				.append(" = '").append(key).append("'").toString();
	}

	/**
	 * @param tableName
	 *            the tableName to set
	 */
	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	/**
	 * @param keyName
	 *            the keyName to set
	 */
	public void setKeyName(String keyName) {
		this.keyColumn = keyName;
	}

	/**
	 * @param valueName
	 *            the valueName to set
	 */
	public void setValueName(String valueName) {
		this.valueColumn = valueName;
	}

	/**
	 * @param step
	 *            the step to set
	 */
	public void setStep(int step) {
		this.step = step;
	}

	/**
	 * @param key
	 *            the key to set
	 */
	public void setKey(String key) {
		this.key = key;
	}

	/**
	 * this method ignore any parameter. please use {@link #generateId()}
	 * <p>
	 * {@inheritDoc}
	 */
	public Long generateId(Object object) {
		return this.generateId();
	}

	@SuppressWarnings("unchecked")
	public boolean support(Class type) {
		return true;
	}
}
